ELLIOTT 903 ALGOL OBJECT CODE
This document contains transcribed and lightly edited text taken from the Elliott 903 Algol Object Code Manual and cross referenced from the Algol Interpreter source code. The edits includes corrections for obvious spelling mistakes and handwritten notes from the original document.
To show where page breaks occur in the original document, page links are included in this document in the form [--PAGE nn--]. Clicking on these links transfers to a scanned image of the page from the original document.
N.B. Additional explanatory text, like this, that did not appear in the original document is coloured red.
Andrew Herbert April 2024
CF The intention of this is to make a partial
stack entry before jumping to a procedure
body.
"address:= N+BA;
L1: store EP at SP; store SP in Entry Pointer
register; add 1 to SP; store PP at SP;
add 1 to SP;
PP:= address;"
[CODE] [FLOWCHART]
CFF This is for a call of a formal function.
"Find FP using BN; address:= contents of
3n+FP; go to L1 in CF above;"
[CODE] [FLOWCHART]
GT An ordinary GO TO is executed by reference
to two words in QACODL, of which the first
contains the label address and the second
the Block Number. The Block Number is
needed in case a jump to an outer block
is involved.
"address:= N+QACODL;
L2: if BN equals contents of (address + 1)
then go to contents of address;
L3: if contents of (EP+3) equals contents
of (address + 1) then to to L4;
EP:= contents of EP; go to L3;
L4: if contents of (EP+2) <O then go to L5;
SP:= contents of (EP+2);
FP:= SP-3; go to L6;
L5: SP:= EP;
L6: EP:= contents of EP;
BN:= contents of (EP+3);
go to contents of address;"
[CODE] [FLOWCHART]
GTF "Find FP using BN; address: = contents of
(3n+FP); go to L2 in GT above;"
[CODE] [FLOWCHART]
GTFS "Find FP using BN; address: = contents of
(3n+FP); go to L7 in GTS below;"
[CODE] [FLOWCHART]
GTS "address: = N+QACODL;
L7: subtract 3 from SP; get integer from
stack; if integer is zero or greater
than contents of address then FAIL;
address: = 2 x integer -1 + address; go to
L2 in GT above;"
[CODE] [FLOWCHART]
IFJ "subtract 3 from SP; get boolean (integer) from
Stack; if zero then go to address N+BA;"
[CODE] [FLOWCHART]
IFUN This stacks the address of a function name if
n= 0 or of a parameter if n ≠ 0,
"Find FP using BN; store(3n+FP) at SP; add
1 to SP; store the constant +1 at SP; add
2 to SP;"
The constant +1 indicates that the address is
that of an integer or boolean variable; this
is checked at a procedure entry against the
parameter checking word.
[CODE] [FLOWCHART]
INDA The purpose of this is to place the absolute:
address of an array element in the stack having
been given the address of the map entry and n
index values, If the array has real elements
then the most significant digit of the result
is a one, picked up from the array map. Next
to this is placed +1 for an integer or +2 for a
real array element.
[CODE] [FLOWCHART]
INDR As for INDA except that the value of the array
element is brought to the stack and unpacked
into 3 locations if real.
[CODE] [FLOWCHART]
INDS "address: = N+QACODL; subtract 3 from SP;
get integer from stack;
if integer is zero or greater than contents of
address then FAIL;
store 2 x integer -l +address at SP; add 3 to
SP;"
[CODE] [FLOWCHART]
INOUT See section 9; the address part of the pord, p,
determines the action in an identical way to
that of the address part of a PRIM pord.
[DESCRIPTION] [CODE] [FLOWCHART]
MAMPS This operation is executed immediately after
entry to a block in which local arrays are declared.
The number of dimensions, d, and arrays, a, are
packed with 6 bits each at the right hand end
of the word containing MAMPS,
begin real array A,B,C,D [P:Q, R:S, T:U];
is translated to
TIR P
TIR Q
TIR R
TIR S
TIR T
TIR U
MAMPS 3,4
A: /0 0 / indicates real
3 7 3 dimensions; 7 locations
onwards to map address
B: /0 0
3 5
C: /0 0
3 5
D: 0 0
3 1
+0 / Map address filled in here
by action of MAMPS (equal to
SP).
The indications "A:" etc do not mean that a global
label is punched, merely that reference to array
A is by specifying the address of the "array pair"
marked "A:".
Using the top six entries in the stack an array
map is calculated and placed in the stack, advanc-
ing SP appropriately, The array map fora d,
dimensional array contains 2d + 2 words in all.
These are arrayed as follows (for d =3):-
of the word containing MAMPS.
array map : DIMENSIONS
TOTAL SIZE
OFFSET
l1
c1
l2
c2
l3
Note that there is one more lowbound value, l,
than map coefficient, c, TOTAL SIZE is the
number of locations occupied by the array itself,
OFFSET is the number of locations between the
leading element of the array and the element all
of whose index values are zero; it is positive if
the element with zero indices lies at a higher
address than the leading element.
The coefficients cl, c2 etc are calculated as
follows:-
c1 is the range of the first subscript multiplied
by two if the array is real.
c2 is the range of the second subscript multiplied
by cl.
The lowbound values l1, l2 etc are not necessary
for the evaluation of the address of an element
of the array, but are necessary for the standard
procedure lowbound,.
The address of the leading element of each array
is filled in at A:, B: etc., the first being
equal to SP, the next to SP + TOTAL SIZE etc.
OFFSET is then calculated
OFFSET = - 2 x P - R × c1 - T × c2
A "pointer pair" is created in QAVNDA - first
pointer points to array, second to map.
Finally there is a jump to execute the next pord
beyond the map address.
The address of element B [i,j,k] is -
the contents of location B: with its "/" to
indicate real plus
OFFSET
plus
2i + j × c1 + k × c2
[CODE] [FLOWCHART]
PE This operation is at the head of a block bearing
the number BN' and expecting m parameters. The
action is to complete the stack entry set up by
CF or by CFF, and do parameter checking (see Section 8
page 27, page 28).
BN occupies 9 bits, m 4 bits.
"store EP-3m at SP; add 1 to SP; store (old)
BN at SP; add 1 to SP; store BN' in Block
Number register; store EP-3m-3 in Formal Pointer
register;"
[CODE] [FLOWCHART]
PEM This is placed at the head of a piece of machine
code to make it look like pords when called from
within the User's Algol program.
Example.
[ ARCTAN ]
ARCTAN PEM 1
+0 for return address
...
...
...
0 ARCTAN+1 normal exit in machine
/8 1 code
The stack entry is completed as for a PE operation
but using the current value of BN in place of BN’,
There is then a call of the machine code from within
the interpreter, On returning to the interpreter
in the normal way for a machine code subroutine
the action for RETURN (see 7.2 below) are executed.
[CODE] [FLOWCHART]
PRIM Enter a subroutine at address N+PBA.
[DESCRIPTION] [CODE] [FLOWCHART]
RFUN This stacks the address of a real type procedure
or a real parameter so that an assignment can be
made to it.
"find FP using BN;
store FP+3n + /0 0 at SP; add 1 to SP;
store /0 2 at SP; add 2 to SP;"
The sign bit on the address word indicates a real
address, and the sign bit on the +2 indicates an
unpacked quantity. The +2 indicates a real quantity
for parameter checking (see page 27, page 28).
[CODE] [FLOWCHART]
TA "store N+BA at SP; add 3 to SP;"
[CODE] [FLOWCHART]
TF ) "find FP using BN;
TFAI ) store contents of (3n+FP) at SP;
TFAR ) store contents of (3n+FP+1) at SP+1;
TFVI ) store contents of (3n+FP+2) at SP+2;
TFVR ) add 3 to SP;"
[CODE] [FLOWCHART]
TIA "store N+QAVNDA at SP; add1 to SP; store +1
at SP; add 2 to SP;"
[CODE] [FLOWCHART]
TIC "store contents of (N+QACODL) at SP; add 3 to SP;"
[CODE] [FLOWCHART]
TICA) "store N+QACODL + the constant 8 O at SP;
TLA ) add 1 to SP; store +l at SP; add 2 to SP;"
The +1 written by TLA gets overwritten by +9 if
a label is an actual parameter.
[CODE] [FLOWCHART]
TIR "store contents of (N+QAVNDA) at SP; add 3 to SP;"
[CODE] [FLOWCHART]
TRA "store N+QAVNDA + the constant /0 0 at SP; add
1 to SP; store +2 at SP; add 2 to SP;"
[CODE] [FLOWCHART]
TRC "store contents of (N+QACODL) at SP; unpack the
contents of (N+1+QACODL) and store at SP+1, SP+2;
add 3 to SP;"
[CODE] [FLOWCHART]
TRCA "store /8 0 plus N+QACODL at SP; store +2 at
SP+l; add 3 to SP;"
[CODE] [FLOWCHART]
TRCN "Find FP using BN; address := contents of
3n+FP; store contents of address at SP;
if address has sign bit =1 then
begin if contents of 3n+FP+l has
sign bit =l1 then transfer contents
of (address +1) to SP+1 and (address +2)
to SP+2 else unpack contents of (address
+1) and transfer to SP+1, SP+2 end;
add 3 to SP;"
[CODE] [FLOWCHART]
TRR "store contents of (N+QAVNDA) at SP; unpack
the contents of (N+1+QAVNDA) and store at
SP+1, SP+2;
add 3 to SP;"
[CODE] [FLOWCHART]
UJ "PP: = N+BA"
[CODE] [FLOWCHART]
TRAP "store /8 0 plus N+BA at SP;
store +2 at SP+1; add 3 to SP;"
This is only for referring to real constants in
hand porded programs, This function is not
produced by the translator.
[CODE] [FLOWCHART]
CBL This has the same effect as a function
CF to a point two pords on and therefore
makes a partial stack entry.
[CODE] [FLOWCHART]
CHECK These punch "newline, asterisk" followed
by a boolean, integer or real whose
value is at the top of the stack or a
string whose address is at the top of
the stack, SP is unchanged except
for CHECKS which reduces it by 3.
CHECKI [CODE] [FLOWCHART]
CHECKR [CODE] [FLOWCHART]
CHECKB [CODE] [FLOWCHART]
CHECKS [CODE] [FLOWCHART]
DO This makes use of the common procedure
ASSIGN (see below).
"ASSIGN; store PP at EP+1;
store contents of (EP+2) in Pord Pointer
register;"
[CODE] [FLOWCHART]
STW "ASSIGN; "
[CODE] [FLOWCHART]
FINISH Punch 100 rows of blank tape, the word
FINISH and a halt code. Then stop.
[CODE] [FLOWCHART]
FOR A stack entry is made. In the object
program FOR is followed by three pords.
PRIM FOR
a address of controlled statemen
BN'
b address of next statement
"store EP at SP;
store (PP+4) at SP+1;*
store a + /0 0 at SP+2;
store old BN at SP+3;
store b at SP+4;
EP: = SP; add 5 to SP;
store BN’ in Block Number register;"
[CODE] [FLOWCHART]
FR This ends a controlled statement.
"pp; = contents of (EP+1);"
[CODE] [FLOWCHART]
* PP+4 points to 5 locations after PRIM FOR
FSE This undoes the effect of FOR and is
the last for list element.
"BN: = contents of (EP+3);
PP: = contents of (EP +4);
SP: = EP; EP: = contents of EP;"
[CODE] [FLOWCHART]
DIV See arithmetic primitives.
[CODE]
ITOR1 Convert contents of SP-3 and SP-6 from
ITOR2 integer to unpacked real respectively.
ITOR1 [CODE] [FLOWCHART]
ITOR2 [CODE] [FLOWCHART]
NEGI Replace the contents of SP-3 by minus
NEGR the contents.
NEGI [CODE] [FLOWCHART]
NEGR [CODE] [FLOWCHART]
RETURN Used at the end of a block or procedure.
"BN: = contents of (EP+3);
SP: = contents of (EP+2);
PP: = contents of (EP+1);
EP: = contents of EP;
FP: = contents of (EP+2) minus 3;"
[CODE] [FLOWCHART]
RTOI1 Convert contents of SP-3 from unpacked
real to integer with FAIL if overflow.
[CODE] [FLOWCHART]
ST This makes use of the common procedure
ASSIGN (see below)
"ASSIGN; subtract 3 from SP;"
[CODE] [FLOWCHART]
STA "ASSIGN; copy the contents of SP to SP-3
(SP+1) to SP-2
(SP+2) to SP-1;"
[CODE] [FLOWCHART]
STEP "ASSIGN; store PP at EP+1;
clear location EP+7;"
[CODE] [FLOWCHART]
WAIT Halt but prepare to resume after a
start at 9.
[CODE] [FLOWCHART]
UNTIL "If the contents of (EP+7) are zero
then make them non zero else add the
contents of (EP+8) to the variable
whose address is at EP+5;
If the sign of ( the increment held
at EP+8 times ( the controlled variable
whose address is at EP+5 minus the final
value given in (EP+11)) is greater than
zero then store PP at EP+1; this corres-
ponds to element exhausted;
subtract 6 from SP;
If the above sign is ≤ O then store
the contents of (EP+2) in the pord
pointer register; this causes the
statement to be executed;"
The type of arithmetic is determined *
by the address of the controlled
variable held at EP+5.
* packing is determined by EP+5.
[CODE] [FLOWCHART]
UP This makes space in the stack for the
result of a type procedure.
"Add 3 to SP;"
[CODE] [FLOWCHART]
WHILE If the topmost value is false then the
next pord is taken, but if true then
a pord jump occurs to the address
given in EP+2.
"subtract 3 from SP;
if false store PP in EP+1;
if true store contents of (EP+2) in
Pord Pointer register;"
[CODE] [FLOWCHART]
procedure ASSIGN;
"subtract 3 from SP;
address: = contents of (SP-3);
type: = contents of (SP-2);
if address has an "8 0" bit then
FAIL because assignment to a
constant is being attempted;
store contents of SP at address;
if address < O then begin, if type
< O then
transfer contents of (SP+1) to
address+1 and contents of (SP+2)
to address +2
else
pack together the contents of (SP+1)
and (SP+2) with round off and store
at address +1
end; "
PRIM28 R↑I→R [CODE] (This PRIM was omitted in the original document.)
PRIM30 I+I→I [CODE]
PRIM31 R+R→R [CODE]
PRIM32 I-I→I [CODE]
PRIM33 R-R→R [CODE]
PRIM34 I×I→I [CODE]
PRIM35 R×R→R [CODE]
PRIM36 I/I→R [CODE]
PRIM37 R/R→R [CODE]
PRIM38 I↑I→I [CODE]
PRIM39 I↑I→R [CODE]
PRIM40 R↑R→R [CODE]
PRIM41 I<I→B [CODE]
PRIM42 R<R→B [CODE]
PRIM43 I≤I→B [CODE]
PRIM44 R≤R→B [CODE]
PRIM45 I=I→B [CODE]
PRIM46 R=R→B [CODE]
PRIM47 I≠I→B [CODE]
PRIM48 R≠R→B [CODE]
PRIM49 I>I→B [CODE]
PRIM50 R>R→B [CODE]
PRIM51 I≥I→B [CODE]
PRIM52 R≥R→B [CODE]
PRIM53 B∧B→B [CODE]
PRIM54 B∨B→B [CODE]
PRIM55 B≡B→B [CODE]
PRIM56 B⊃B→B [CODE]
The primitives numbered 12 (DIV) and 30-56 have two inputs and
one output. The left hand input is at SP-6, the right
hand input is at SP-3. The output occupies SP-3 or,
if real, the three words starting at SP-3. The nett
effect of each primitive is to reduce SP by 3.
PRIM57 ¬B→B [CODE]
PRIM58 ABS [CODE]
PRIM59 ENTIER [CODE]
PRIM60 EXP [CODE]
PRIM61 LN [CODE]
PRIM62 SIGN [CODE]
The primitives numbered 58-62 are the ones which
execute the Algol procedures which are always in the
store. A call of one of these procedures does not
produce a PRIM UP as an ordinary procedure call would,
The actions of all these primitives are:-
"replace contents of (SP-3) by the function of
the contents".
PRIM63 | [CODE]
PRIM64 | These place integer [CODE]
PRIM65 | x in the stack at SP-2 [CODE]
| where x runs from 3 [CODE]
PRIM66 | to 10 for primitives [CODE]
PRIM67 | 63-70. The purpose [CODE]
PRIM68 | is for parameter [CODE]
PRIM69 | checking. [CODE]
PRIM70 | [CODE]
The primitives numbered 63-70 serve the purpose
of filling the stack with type information alongside the
address of any call-by name actual parameter, This
is for parameter checking.